/*************************************************************************
    > File Name: slave0.c
    > Author: wusihai
    > Mail: wusihai18@gmail.com 
    > Created Time: Sun 16 Feb 2020 02:28:15 PM CST
 ************************************************************************/

#include <stdio.h>
#include "slavertm.h"

#include <slave.h>
#include <math.h>
#include "register.h"
#include <simd.h>

#define xx 8
#define yy 8
#define zz 60

//索引宏
#define n3d_ext(ix,iy,iz)   ix*SubNy*SubNz+iy*SubNz+iz
void Smerge(rtm_slave_merge* p){
  //答应字
  volatile unsigned int get_reply,put_reply;
  //本地
  rtm_slave_merge par;
  get_reply=0;
  athread_get(PE_MODE,p,&par,sizeof(rtm_slave_merge),&get_reply,0,0,0);
  while(get_reply!=1);

  //获取当前从核号，行号，列号
  volatile unsigned int myid=athread_get_id(-1);
  volatile unsigned int rowid,colid;
  GET_ROW(rowid);
  GET_COL(colid);

  int SubNx=par.SubNx;
  int SubNy=par.SubNy;
  int SubNz=par.SubNz;

  //LDM数据存储
  float In1[xx][yy][zz];
  float In2[xx][yy][zz];
  float In3[xx][yy][zz];
  float Out[xx][yy][zz];

  //CG x-y loop
  int GridLoopX=(par.endX-par.stX+xx*8-1)/(8*xx);
  int GridLoopY=(par.endY-par.stY+yy*8-1)/(8*yy);
  //depth z loop
  int LoopZ=(par.endZ-par.stZ+zz-1)/(zz);

  int ix,iy,iz;
  int tx,ty,tz;
  int XX,YY,ZZ,l;
  int gx,gy,gz;
  int g_x,g_y,g_z;
  int x,y,z;
  int a,b;
  floatv4 v1,v2,v3,v4;

  //从核- X-Y方向 循环反转
  int LX,LY,LZ=0;
  for(ix=0;ix<GridLoopX;ix++){
	gx=ix*8*xx+colid*xx;
	for(iy=0;iy<GridLoopY;iy++){
	  gy=iy*8*yy+rowid*yy;
	  if(gx<(par.endX-par.stX)&&gy<(par.endY-par.stY)){
		//重新确定X-Y计算范围-针对最边缘的CPE.
		((par.endX-par.stX)-gx)>xx?(XX=xx):(XX=((par.endX-par.stX)-gx));
		((par.endY-par.stY)-gy)>yy?(YY=yy):(YY=((par.endY-par.stY)-gy));

		LZ=0;
		//CPE block循环
		for(iz=0;iz<LoopZ;iz++){
		  //重新确定Z的计算范围
		  (par.endZ-par.stZ)-(iz*zz)>zz?(ZZ=zz):(ZZ=(par.endZ-par.stZ)-(iz*zz));
		  gz=iz*zz;
		  LZ=LZ+ZZ;
		  /* 1. Load  In data */
		  get_reply=0;
		  for(tx=0;tx<XX;tx++){
			for(ty=0;ty<YY;ty++){
			  x=par.stX+gx+tx;
			  y=par.stY+gy+ty;
			  z=par.stZ+gz;
			  athread_get(PE_MODE,par.Pin1+n3d_ext(x,y,z),&In1[tx][ty][0],sizeof(float)*(ZZ),&get_reply,0,0,0);
			}
		  }
		  for(tx=0;tx<XX;tx++){
			for(ty=0;ty<YY;ty++){
			  x=par.stX+gx+tx;
			  y=par.stY+gy+ty;
			  z=par.stZ+gz;
			  athread_get(PE_MODE,par.Pin2+n3d_ext(x,y,z),&In2[tx][ty][0],sizeof(float)*(ZZ),&get_reply,0,0,0);
			}
		  }
		  for(tx=0;tx<XX;tx++){
			for(ty=0;ty<YY;ty++){
			  x=par.stX+gx+tx;
			  y=par.stY+gy+ty;
			  z=par.stZ+gz;
			  athread_get(PE_MODE,par.Pin3+n3d_ext(x,y,z),&In3[tx][ty][0],sizeof(float)*(ZZ),&get_reply,0,0,0);
			}
		  }
		  while(get_reply!=(XX*YY*3));
		  /* 2.compuation  add*/
		  for(tx=0;tx<XX;tx++){
			for(ty=0;ty<YY;ty++){
			  for(tz=0;tz<ZZ;tz++){
				Out[tx][ty][tz]=In1[tx][ty][tz]+In2[tx][ty][tz]+In3[tx][ty][tz];
			  }
			}
		  }

		  /* 3. write  Out data */
		  put_reply=0;
		  for(tx=0;tx<XX;tx++){
			for(ty=0;ty<YY;ty++){
			  x=par.stX+gx+tx;
			  y=par.stY+gy+ty;
			  z=par.stZ+gz;
			  athread_put(PE_MODE,&Out[tx][ty][0],par.Pout+n3d_ext(x,y,z),sizeof(float)*(ZZ),&put_reply,0,0);
			}
		  }
		  while(put_reply!=(XX*YY));

		}
	  }

	}
  }
}


